package cn.zwx.spring.health.check.example.health;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.actuate.endpoint.ApiVersion;
import org.springframework.boot.actuate.endpoint.web.annotation.EndpointWebExtension;
import org.springframework.boot.actuate.health.*;
import org.springframework.stereotype.Component;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Set;

/**
 * @description: 自定义返回
 * @projectName:services-manager-example
 * @see:cn.zwx.services.manager.example.common.health
 * @author:zhangwenxue
 * @createTime:2022/1/7 17:37
 * @version:1.0
 */
@Component
@EndpointWebExtension(endpoint = HealthEndpoint.class)
public class MyHealthEndpointWebExtension extends HealthEndpointWebExtension {

    private final Logger logger = LoggerFactory.getLogger(MyHealthEndpointWebExtension.class);

    private final String PING = "ping";

    private final String REDIS = "redis";
    /**
     * Create a new {@link HealthEndpointWebExtension} instance.
     *
     * @param registry the health contributor registry
     * @param groups   the health endpoint groups
     */
    public MyHealthEndpointWebExtension(HealthContributorRegistry registry, HealthEndpointGroups groups) {
        super(registry, groups);
    }

    /**
     * @description  重新写返回逻辑
     * @return org.springframework.boot.actuate.health.HealthComponent
     * @author zhangwenxue
     * @createTime 2022/1/7 18:31
     **/
    @Override
    protected HealthComponent aggregateContributions(ApiVersion apiVersion, Map<String, HealthComponent> contributions,
                                                     StatusAggregator statusAggregator, boolean showComponents, Set<String> groupNames) {
        CompositeHealth compositeHealth = super.getCompositeHealth(apiVersion, contributions, statusAggregator, showComponents, groupNames);
        Map<String, HealthComponent> components = compositeHealth.getComponents();
        HealthComponent healthComponent = components.get(PING);
        HealthComponent healthComponentForRedis = components.get(REDIS);
        Status statusForRedis = healthComponentForRedis.getStatus();
        Status statusPing = healthComponent.getStatus();
        CompositeHealth myCompositeHealth = null;
        if (statusForRedis.equals(Status.DOWN)){
            // 如果Redis 挂了不影响healthCheck 整体状态
            try {
                Class<CompositeHealth> clazz = CompositeHealth.class;
                Constructor<CompositeHealth> constructor = clazz.getDeclaredConstructor(ApiVersion.class, Status.class, Map.class);
                constructor.setAccessible(Boolean.TRUE);
                myCompositeHealth = constructor.newInstance(apiVersion, statusPing, components);
            } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
                logger.error("convert CompositeHealth obj error !",e);
            }
            return myCompositeHealth;
        }else {
            return compositeHealth;
        }
    }

}
